Making GRUB quiet

While traveling, I have been asked a few times by security agents at airports
to turn on my laptop, and well, show them it did work, and looked like a real
computer.

Although they never searched the content and nothing bad ever happend,
every time I cross the border or go through security I am worried about
what might happen, especially given recent stories of people being searched
and their laptops taken away for further inspection.

The fact I use full disk encryption does not help: if I was asked to boot, my
choice would be to either enter the password and login,
thus disclosing most of the content of the disk, or refuse and probably
have my laptop taken away for further inspection.

So.. for the first time in 10 years, I decided to keep Windows on my personal
laptop. Even more, leave it as the default operating system in GRUB, and well,
not show up GRUB at all during boot.

Not because I think it is safer this way, but just to create as little pretexts
or excuses for anyone to further poke at my laptop, in case I need to show it
or they need to inspect it.

Getting grub out of the way was not as easy as it should have been, so this post is
to document what I did.

Problems

First of all, here are the problems:

The Debian GRUB setup scripts create a menu entry in GRUB for each
kernel you have installed, followed by other detected Operating Systems.
This means that every time you install a new kernel, the entry number
of other Operating Systems change (eg, Windows becomes the 3rd entry,
or 4th entry, ...). Given that the default Operating System is specified
by entry number, if you want to default to windows, well, it doesn't
play out well.

By default, GRUB will show a menu. If you disable that menu (relatively
easy), it will still show a "Loading GRUB." message followed by
"Welcome to GRUB!", something like:

LoadingGRUB.WelcometoGRUB!

Turns out that those messages are not configurable,
as they are printed before any config file can be read by GRUB.
Ubuntu and a few other vendors have provided a patched version of GRUB,
but I really don't want to go down that path: don't want to keep installing
my own version of GRUB or patch and recompile for each new release.

So, here's what I did...

Fixing the order of the entries

There might be better ways to provide a default that is not an integer, the
name of an entry, for example. However, I really wanted windows to show up first
in GRUB.

To fix the order of the menu entries, I:

Opened /boot/grub/grub.cfg, and manually copied the entry for Windows I wanted
to keep. In my case, the entry was:

Disabling the boot menu

The first line will tell grub to start Windows by default (the first boot entry), the second one tells
grub to show the menu for 0 seconds by default, thus not showing it,
the 3rd one will wait for 5 seconds for you to press a key before the menu, the last one will not show
the counter going from 5 to 0 before showing the menu.

The only hiccup I had here was that most of the documents say you have to hold shift
to get into the menu, but no, for me I had to press ESC, or any other key? I still
need to try :).

Don't forget to run update-grub and reboot to test this out. You should see that
despite the changes, you will still have a Loading GRUB. message, and a Welcome to GRUB!,
although nothing else will show up before booting Windows.

Disabling the boot messages

So, how do you get rid of the annoying:

LoadingGRUB.WelcometoGRUB!

? Most forums and online discussions will tell you to patch the GRUB source code and
recompile. Those messages are printed out well before any config file can be loaded,
and there are really not that many alternatives.

I really didn't want to patch, as I did not want to maintain a set of patched
binaries for my own use on my own system (yes, I love keeping the system up to date!
And I love playing with testing/unstable, which means frequent updates).

The idea was simple: if the messages are displayed, they must be stored somewhere.
And if any equivalent of printf is used, I can replace the first character of each
of those strings with a \0 to prevent them from showing up.

This is terribly terribly hacky. But 2 hours of work to find the right files and the
right process gave me exactly what I wanted: a tool
that modifies a few of the grub files to remove the messages, which works like a charm.

By adding a hook in /etc/initramfs-tools or /etc/grub.d, I can just run
the tool every time grub configs are changed, without having to recompile and patch the source.

Again, don't expect too much, it's not clean and beautiful, it only works.

What next?

Most distributions used an entirely different path: patching GRUB to unconditionally
disable those messages. As a user, I'd rather prefer to have the choice to disable those
messages or not, especially given the fact that those messages can be useful
for debugging.

Unsurprisingly, the GRUB maintainers refused those patches, which are now maintained
separately by each distro that includes them.

Related to grub-shusher, I will need to update it every time bootstrap.S and a few
other .S files change in GRUB. This doesn't happen often, but I am sure I
will eventually grow tired of maintaining it.

It would still be great to have a real, supported, solution for
configuration parameters that are needed before, well, a configuration file
can be read and loaded.

Here are some proposals:

It would not be hard to add some sort of watermark before each configuration
variable in the .S file, and binary blobs?
Then we could have a tool like grub-shusher that reliably
can find those watermarks, the corresponding variables, and change them directly
into the binary? For example, in bootstrap.S we could have a bool to determine
if messages have to displayed or not, code would check that bool value before
displaying the messages. Before that bool definition, we can add a
watermark like 0xabcd (any value that is not used throughout the binary, really)
to indicate that the following bytes are a configurable bool? Have something
like grub-shusher find those watermarks, and allow to change them. This is
probably worth doing if there are more variables than well, just one.

Ship GRUB with variances of kernel.img, with different parameters compiled
in, and let grub-install figure out which variances to install on the
MBR based on user configs or command line flags. This would work only if there
are a handful of variables, as the number of combinations would explode exponentially.
It seems brittle, but would work.