GRUB How-To
===========


Copyright (C) 2017, 2018, 2019, 2020, 2021, 2022  Kai Mertens <kmx@posteo.net>  

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License".


TODO: This file needs to get reviewed and updated. All steps listed
here (except authentication support) are understood by the toolchain
scripts. Please don't apply these steps manually but use the scripts
instead! See `../doc/toolchain.md` for most recent documentation.

This tutorial hopefully helps to understand how to pack a GRUB
executable elf payload file for the coreboot project. It further shows
how to add Zerocat’s GRUB Configuration File into the generated
`coreboot.rom` to make your machine boot with a nice GRUB Boot Loader
Menu.


Points of Interest
------------------


* <https://www.gnu.org/software/grub/manual/grub/grub.html>
* <http://www.dolda2000.com/~fredrik/doc/grub2>
* <https://blog.fpmurphy.com/2010/06/grub2-modules.html>

    > If a command is entered (either directly or via a script) the
    > appropriate module(s) is loaded if the command is not already
    > registered.

* <https://www.linux.org/threads/understanding-the-various-grub-modules.11142/>
* <https://www.linuxquestions.org/questions/slackware-14/how-to-match-x-keyboard-layout-with-the-the-kernel-keyboard-map-4175455061/>
* <https://www.coreboot.org/GRUB2>
* <https://www.coreboot.org/SeaBIOS> (To see how to chainload an executable GRUB Payload File, or how to use Coreboot VGA Support)


Short Basics about GRUB
-----------------------


During boot, GRUB starts loading the `normal` module and its
dependencies `terminal`, `crypto`, `extcmd`, `boot` and `gettext`. It
then looks for its configuration file and loads additional modules as
required by occurring statements. However, modules that are not loaded
as required by the dependencies have to be loaded explicitly using the
`insmod` command or have to be packed as pre-loaded modules within the
executable `*.elf` payload file. Examples for the latter case are
modules `luks` and `geli` which will make the `cryptomount` statement
work with encrypted disks and LUKS containers.

Basically, three files form a complete GRUB arrangement:

* The GRUB Executable ELF Payload File for Platform i386-coreboot

    `grub2.elf`

* The initial configuration file for platform coreboot

    [grub@2.02_coreboot.cfg][], which will be accessible as

        (memdisk)/boot/grub/grub.cfg

    later on during the running instance of GRUB upon boot.

* Zerocat’s chainloaded GRUB Configuration File

    [grub@2.02_zerocat.cfg][], which will be accessible as

        (cbfsdisk)/etc/zerocat.cfg

    during the running instance of GRUB upon boot.


GRUB File System
----------------


After boot, all packed files of the executable GRUB payload file will
be accessible within GRUB’s `(memdisk)/boot/grub/` default file system.
On GRUB’s command line, you may use `ls` and `cat` to check folder and
file contents, and `insmod` to extend GRUB’s functionality.


### Important Files within the GRUB File System


* (memdisk)/boot/grub/i386-coreboot/command.lst

    Provides information about which module provides a given command.

* (memdisk)/boot/grub/i386-coreboot/moddep.lst

    Provides information about module dependencies.

    In example: If module `normal` gets loaded, its dependencies
    `terminal`, `crypto`, `extcmd`, `boot` and `gettext` will be loaded
    as well.

* (memdisk)/boot/grub/grub.cfg

    GRUB’s first configuration file.


Coreboot’s GRUB Configuration File
----------------------------------


Note the content of GRUB’s first configuration file
[grub@2.02_coreboot.cfg][] as provided by Zerocat.

This file will be packed into GRUB’s file system `(memdisk)/boot/grub/`
as `grub.cfg`. Please verify that its first line contains the “set
prefix” statement, otherwise GRUB will issue error messages during
boot. The advantage of referencing a custom `grub.cfg` outside the GRUB
file system – i.e.: `(cbfsdisk)/etc/zerocat.cfg` – is that you needn't
generate the executable GRUB payload file again once your are updating
your GRUB configuration.


Get GRUB Sources
----------------


    $ git clone git://git.savannah.gnu.org/grub grub-2.02
    $ cd grub-2.02

Let’s use a tagged version: 2.02

    $ git checkout 2.02

Then configure and compile:

    $ ./autogen.sh
    $ ./configure --with-platform=coreboot
    $ make

This will also generate some `*.pf2` font files as like `ascii.pf2`
or `unicode.pf2` for example. Or like `dejavu_14.pf2` in case the DejaVu
Fonts are installed on your system. Play around with `grub-mkfont` in
case you want to generate your custom `*.pf2` font. Note we choose
`unicode.pf2` as default when it comes to pack the elf executable
payload file in next section.

Finally, install GRUB locally in order to put all files in place before
you proceed:

    $ sudo make install

(You might uninstall GRUB with `$ sudo make uninstall` later on.)


Pack Your GRUB Payload File
---------------------------


A dedicated shell script with rich keyboard layout support is part of
the toolchain: `../src/gen-payload-grub.sh`

This script generates a bunch of layout files and creates a code
snippet for Zerocat’s GRUB Configuration File, for instance:

    ---------8<-------------cut here cut here cut here----------------->8---------
    # Keymap --- several options available, adapt to your needs:
    # us gb fi dk se hu cz pl bg ro tr fr pt es it nl be de
    # ca_fr tr_f ch_de ch_fr
    # us_intl us_dvorak fr_latin9 de_nodeadkeys sk_qwerty
    keymap us
    ---------8<-------------cut here cut here cut here----------------->8---------

Another code snippet is generated and will be picked by the script when
it comes to pack the payload file with the bunch of layout files amoung
others.


### Adding SeaBIOS Payload


GRUB is able to chainload other payloads, so we suggest to add
*SeaBIOS* as well. This will allow you to run the [Qubes OS Installer][]
while having GRUB’s authentication support still available
as an option. Furthermore, SeaBIOS provides basic access to TPM chips,
if available.


#### Download and Configure


The SeaBIOS executable elf payload file has to be built externally.
Sources can be downloaded and configured. Let's use a tagged version:

    $ git clone https://git.seabios.org/seabios.git
    $ cd seabios
    $ git checkout rel-1.12.0
    $ make menuconfig

Within the `menuconfig` tool, select the coreboot build target:

    General Features --->
    - Build Target (Build for coreboot) --->


##### Configure SeaBIOS with VGABIOS


In case you selected ...

    Devices --> Graphics initialization = ‘Use native graphics init’

... within the coreboot configuration, now configure SeaBIOS with:

    VGA Rom --> VGA Hardware Type “(Coreboot linear framebuffer)”

Examples given: ThinkPad X200, X230, T430, etc.


##### Configure SeaBIOS without VGABIOS


In case you selected ...

    Devices --> Graphics initialization = ‘Run VGA Option ROMs’

... within the coreboot configuration, now configure SeaBIOS with:

    VGA Rom --> VGA Hardware Type (None)

Example given: T60 with ATI Graphics


#### Compile and Add


Now compile SeaBIOS:

    make

A VGA wrapper called `out/vgabios.bin` will be created by SeaBIOS and
this file has to be added to your `coreboot.rom` later on:

    $ cd coreboot/
    $ build/cbfstool build/coreboot.rom add -t raw -n vgaroms/vgabios.bin -f path/to/your/seabios/out/vgabios.bin
    $ build/cbfstool build/coreboot.rom print

In any case, add the SeaBIOS executable payload file to the `coreboot.rom`:

    $ build/cbfstool build/coreboot.rom add-payload -n seabios.elf -f path/to/your/seabios/out/bios.bin.elf
    $ build/cbfstool build/coreboot.rom print

Done.


Zerocat’s GRUB Configuration File
---------------------------------


Let’s use Zerocat’s GRUB Configuration File (with code snippets copied
from the libreboot project) to start with. Note we use this file on
ThinkPad Laptops – in case you want to use it for Desktop Boards, it
should work just fine. You might add some additional `insmod`
statements, though.

Two important statements are provided in order to support command
`cryptomount`, which is used to boot from encrypted devices and LUKS
containers:

    insmod luks
    insmod geli

Available for download: [grub@2.02_zerocat.cfg][]

This file has to be copied into the coreboot file system by means of
coreboot’s `cbfstool`:

    $ build/cbfstool build/coreboot.rom add -n etc/zerocat.cfg -t raw -f path/to/your/grub@2.02_zerocat.cfg
    $ build/cbfstool build/coreboot.rom print

Adjust paths as required. Make sure option `-n etc/zerocat.cfg` matches
the source path as specified in GRUB’s first configuration file
[grub@2.02_coreboot.cfg][] as provided by this project.


### GRUB’s Authorization Support


The configuration file comes with a pre-defined set of GRUB users and
corresponding clear text passwords:

    password user0 topsecret0
    password user1 topsecret1
    password user2 topsecret2

Super cow power is granted to user ‘user0’, but other users can be
specified as well if you use a space separated list. Setting the
variable `superusers` to any value – including `""` – actually
activates GRUB’s authentication support:

    set superusers="user0"

This setup improves your security as it restricts access to the GRUB
boot menu in the following manner:

* Hotkeys ‘e’ and ‘c’ (“edit menu entry” and “enter a command line”)
  are accessible for superusers only, i.e. ‘user0’.

* Menu entries which carry the option `--unrestricted` will remain
  accessible for everybody, as long as option `--users` is not present.

* Menu entries are accessible *for superusers and users only* as soon
  as you add option `--users "user1 user2"` to the `menuentry` command.

* To disallow access for *all* users (but not superusers), just provide
  option `--users ""` – or omit the option completely.

WARNING: Playing around with authentication can be dangerous, as it
will easily lock you out from accessing any hard disk or USB rescue
system! Be aware of what you are doing, always double check your
settings. Provide at least one unrestricted menu entry to boot your
disk until you get confidence that all other settings work as intended.
Note commands `password` and `password_pbkdf2` are expecting *two*
arguments, provided in the same line, separated by one ‘space’
character only. Disobey this rule and you will have to spend time and
money in order to re-flash your device!

NOTE: In order to *disable* GRUB’s authentication support per default,
`set superusers="user0"` has been turned into a comment line. Remove
the preceding hash character (`#`) if you really want to activate
GRUB’s authentication support! *Please adjust user names and passwords
to your needs!* You can improve the level of security by using hashed
passwords instead of clear text ones. See
<https://www.gnu.org/software/grub/manual/grub/grub.html#Security> for
details.


Done!
-----


Your Coreboot ROM should now contain a valid GRUB payload
configuration.



[README]:                             ../doc/README.md
[grub@2.02_modules-install.conf]:     ../templates/grub@2.02_modules-install.conf
[grub@2.02_coreboot.cfg]:             ../templates/grub@2.02_coreboot.cfg
[grub@2.02_zerocat.cfg]:              ../templates/grub@2.02_zerocat.cfg
[Qubes OS Installer]:                 https://www.qubes-os.org/
