All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Cc: Chris Murphy <lists@colorremedies.com>, Michael Chang <mchang@suse.com>
Subject: Re: RFC: A partition for grubenv, etc.
Date: Thu, 27 May 2021 15:49:14 -0300	[thread overview]
Message-ID: <CAJq09z6zjOgkWiTCrJ+rNa5V_qO2hdf1=MsjUX0uiUmVLM1S1g@mail.gmail.com> (raw)
In-Reply-To: <20210527085942.GA8422@mercury>

This was already discussed in this ML a couple of times.

It is not uncommon for some FS to have an unused header space. This
happens for btrfs and SUSE patches grub2 to use it:
https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-grubenv-in-btrfs-header.patch?expand=1.
It is a "workaround", specific for a single FS that needs to be
redesigned for each FS where grub cannot write to.
Its complexity grows with each new FS.

I think that grub should offer an alternative way to store grubenv
independently from FS in use. Grub already requires some spare space
for stage 1.5 and grub could use the remaining space after that for
grubenv. For BIOS with DOS partitions, it uses the blocks between
MBR and the first partition (sector 63 or 2048 for recent disks). For
BIOS with GPT, grub already requires a grub-bios partition (normally
way bigger than needed). And for UEFI, as it was already mentioned,
there is an EFI partition. I know I'm not considering anything
but x86 but it is where this issue happens. A new dedicated partition
might be overkill and only mostly only useful for GPT, where there
are already partitions dedicated for booting (grub bios boot or EFI).

My proposal would be an additional source for grubenv. SUSE still uses
the FS /boot/grub2/grubenv to store a
env_block variable (as well as other variables) that, if present, will
point to where an additional grubenv should be. My proposal is quite
the same,
but not limited to BTRFS.

grub2-mkconfig could be opportunistic, using only /boot/grub2/grubenv
when it is writable by grub, /boot/EFI when present, btrfs first
blocks or stage1.5 data when everything
else fails. Grub and userland tools would only need to check if the
"normal" grubenv does define a "$grubenv_device", "$grubenv_block" or
"$grubenv_include".

As it was mentioned, grubenv should be grub.cfg specific, not image
specific. As /boot/grub2/grubenv is still in use, each grub.conf would
still point to a different grubenv file that would include
a different grubenv_{device,block,include}. grubenv could contain an
uuid variable to help grub2-mkconfig and grub iteratively look for a
matching grub_block or allocate a new slot.
Something like this:

/boot/grub2/grubenv
grubenv_device=(hd0,msdos4)
grubenv_block=0 # for btrfs
grubenv_maxblock=64 # for btrfs 0x10000 (btrfs header location) /
0x400 (grubenv size)
# grubenv_block=1234 for stage1.5 area where 1234 is the stage1.5 size in blocks
grubenv_uuid=3dfd5d2a-7314-47dc-ba5a-e02aa2b00749

(hd0,msdos4)@0
grubenv_uuid=3dfd5d2a-7314-47dc-ba5a-e02aa2b00749
next_boot=2

With a simple grub.cfg scriptlet (using not valid syntax):

if [ "$grubenv_include" ]; then
   # for EFI
   load_env $grubenv_include
fi
if [ "$grubenv_device" ] && [ "$grubenv_block" ]; then
  for n in {1..$grubenv_maxblock}; do
     if [ "$grubenv_uuid" ]; then
       expected_uuid=$grubenv_uuid
       load_env -d $grubend_device -b $grubenv_block grubenv_uuid
       if [ "$grubenv_uuid" != "$expected_uuid" ]; then
         grubenv_uuid=$expected_uuid
         grubenv_block++
         continue
       fi
     fi
     # I hope it checks the header...
     if ! load_env -d $grubend_device -b $grubenv_block; then
       # not found or failed
       grubenv_device=
       grubenv_block=
     fi
     break
  fi
...
if [ "$grubenv_device" ] && [ "$grubenv_block" ]; then
   save_env -d $grubend_device -b $grubenv_block grubenv_uuid
fi

The problem is that the location of every single /boot/grub2/grubenv
is not deterministic. It would be hard to safely garbage-collect
unused grubenv blocks.
I think that whenever grub2-editenv writes a block, it should
rightshift the available area ($grubenv_maxblock) and add or move the
modified grubenv to position 0
(the hottest block). Eventually all unused grubenv blocks will be
dropped during the rightshift.

I'm not trying to solve every single corner case but I'm suggesting
changes that would empower the OS to solve the issue (requiring a
partition with writable FS for grubenv).
For most cases where grubenv is not writable today, it could
automatically solve the issue. For others where multiple complex
grub.conf/grubenv are in use,
it would give tools to the advanced user to manually solve the issue.
I'm not worried about advanced users because they can today create a
dedicated fat32 partition with
manually defined grubenv path. I'm thinking about distributions and
the general user that marginally knows what grub is.

Regards,

---
     Luiz Angelo Daros de Luca
            luizluca@gmail.com


  reply	other threads:[~2021-05-27 18:49 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-25 22:58 RFC: A partition for grubenv, etc Chris Murphy
2021-05-26  8:07 ` Konrad Rzeszutek Wilk
2021-05-26  8:35   ` Toomas Soome
2021-05-27  2:23   ` Chris Murphy
2021-05-26  9:16 ` Michael Chang
2021-05-27  2:36   ` Chris Murphy
2021-05-27  8:59     ` Michael Chang
2021-05-27 18:49       ` Luiz Angelo Daros de Luca [this message]
2021-05-27 23:10         ` Chris Murphy
2021-05-28  3:42         ` Michael Chang
2021-05-27 22:08       ` Chris Murphy
2021-07-28 12:23         ` Daniel Kiper
2021-09-24  2:59           ` Chris Murphy
2021-10-26 14:22             ` Daniel Kiper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJq09z6zjOgkWiTCrJ+rNa5V_qO2hdf1=MsjUX0uiUmVLM1S1g@mail.gmail.com' \
    --to=luizluca@gmail.com \
    --cc=grub-devel@gnu.org \
    --cc=lists@colorremedies.com \
    --cc=mchang@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.