Re: How to use serial console to enter GELI password to boot kernel on a GELI encrypted ZFS pool

From: Guido van Rooij <guido_at_gvr.org>
Date: Fri, 19 Aug 2022 08:20:21 UTC
On Wed, Aug 17, 2022 at 09:19:42AM -0600, Warner Losh wrote:
>    On Wed, Aug 17, 2022 at 7:35 AM Guido van Rooij <[1]guido@gvr.org>
>    wrote:
> 
>      On 16 Aug 2022, at 19:09, Warner Losh <[2]imp@bsdimp.com> wrote:
> 
>    
>    On Tue, Aug 16, 2022 at 3:44 AM Guido van Rooij <[3]guido@gvr.org>
>    wrote:
> 
>      On Mon, Aug 15, 2022 at 02:20:32PM -0600, Warner Losh wrote:
>      >Â  Â  On Mon, Aug 15, 2022 at 8:23 AM Guido van Rooij
>      <[1][4]guido@gvr.org>
>      >Â  Â  wrote:
>      >
>      >Â  Â  Â  Currently I have a system with ZFS on GELI. I use the
>      ability in
>      >Â  Â  Â  the EFI loader to enter the GELI password.
>      >Â  Â  Â  Is it possible somehow to use a serial console to enter
>      the
>      >Â  Â  Â  password?
>      >Â  Â  Â  My system does have a COM1 port but it isn't recognised at
>      the early
>      >Â  Â  Â  bot stage. There I only see:
>      >Â  Â  Â  ÃÂ  ÃÂ  Consoles: EFI console
>      >Â  Â  Â  ÃÂ  ÃÂ  GELI Passphrase for disk0p4:
>      >Â  Â  Â  (Note: this is early in the boot process so there is no
>      access to
>      >Â  Â  Â  boot.config (or any other file in the ZFS pool) as it
>      still on
>      >Â  Â  Â  encrypted storage at that time).
>      >
>      >Â  Â  The boot loader.efi will read ESP:/efi/freebsd/loader.env for
>      >Â  Â  environment
>      >Â  Â  variables. You can use that to set the COM1 port since it
>      appears your
>      >Â  Â  EFI system doesn't do console redirection.
>      >Â  Â  If you want it to only prompt COM1 for the password, but
>      everything
>      >Â  Â  else is
>      >Â  Â  on the efi console, that's a lot harder.
>      Hi Warner,
>      Thanks, but somehow I still cannot get it to work properly.
>      Content of /efi/freebsd/loader.env:
>      boot_multicons="YES"
>      console="efi comconsole"
>      The boot prompt still only shows "Consoles: EFI console".
> 
>    Yes. That's printed before we process the ESP file and switch to the
>    new console...
>    Â
> 
>      When I boot I get the GELI passphrase prompt at the EFI console
>      only. But when the kernel starts
>      to run I do get output to the serial console, staring with:
>      ---<<BOOT>>---
>      Copyright (c) 1992-2021 The FreeBSD Project.
>      So it seems the loader.env file is read correctly (it didn't output
>      anything to the serial
>      console before I created efi/freebsd/loader.env). But looking at the
>      source I see in
>      efi/loader/main.c:read_loader_env():
>      Â  Â  Â  Â  if (fn) {
>      Â  Â  Â  Â  Â  Â  Â  Â  printf("Â  Â  Reading loader env vars from
>      %s\n", fn);
>      Â  Â  Â  Â  Â  Â  Â  Â
>      parse_loader_efi_config(boot_img->DeviceHandle, fn);
>      Â  Â  Â  Â  }
>      I never saw the printf appearing. I do not understand this.
> 
>    It should have appeared on the video console of the EFI console
>    (assuming no serial
>    redirect is going on in that BIOS).
> 
>    It surely did not.
> 
>    I'd have to delve more deeply into the prompts for the GELI password
>    than I have
>    time to do this morning. What if you type the password blind into the
>    serial port?
> 
>    Tried that but nothing happened. When I
>    enter the passphrase after typing it in via
>    the serial port, it worked immediately so
>    we can conclude that no single keystrokeÂ
>    got through.
> 
>    OK. I'll have to delve a little more deeply then...

I Think I know why it does not work. The "Consoles:" line is printed in cons_probe()
which is called in main():
        setenv("console", "efi", 1);
        cons_probe();
So that explains why we see Consoles: EFI console
Then we see in main():
        for (i = 0; devsw[i] != NULL; i++)
                if (devsw[i]->dv_init != NULL)
                        (devsw[i]->dv_init)();
The way I understand it, is this the place where the GELI passphrase prompt originates
from.
But only after that, we see the call to load /efi/freebsd/loader.env

Shouldn't the dv_init() calls be moved to after the call to boot_howto_to_env(howto)?

Regards,

-Guido