Re: Still did not succeed to boot on Lenovo Yoga C630

From: Hiroo Ono (小野寛生) <hiroo.ono+freebsd_at_gmail.com>
Date: Sun, 25 Dec 2022 01:46:37 UTC
2022年12月24日(土) 10:03 Warner Losh <imp@bsdimp.com>:
>
>
>
> On Fri, Dec 23, 2022 at 5:49 PM Hiroo Ono (小野寛生) <hiroo.ono+freebsd@gmail.com> wrote:
>>
>> The current status of FreeBSD 14-current on Lenovo Yoga C630 is as follows:
>>
>>  1) Merging from OpenBSD's loader code made the loader boot apart from
>> 3 points (#2 to 4 ).
>>  2) when comconsole->c_init() runs the 2nd time, it seems to freeze.
>> (might be C630 specific)
>>  3) SetVirtualAddressMap() in efi_do_vmap() freezes. (might also
>> affect other snapdragon systems like Microsoft Arm Developer Kit)
>>  4) The kernel is kicked but does not start.
>>
>> 1) is quite straightforward. What needs to be changed is
>> stand/efi/loader/arch/arm64/start.S.
>
>
> Can you share what needs to be done? To my eye, we don't need any changes, so it would be good to know what you've had to do exactly.
>
>>
>> For 2), I do not know what to do. Currently, I commented out
>> comconsole from struct console *consoles[] in stand/efi/loader/conf.c
>> as a workaround. Maybe, I should write a fault handler that helps
>> returning from the fault.
>
>
> There were problems with this with HyperV on aarch64 too.
>
> Something like
> diff --git a/stand/efi/loader/efiserialio.c b/stand/efi/loader/efiserialio.c
> index 8b3f8e83e0b3..54ee39096685 100644
> --- a/stand/efi/loader/efiserialio.c
> +++ b/stand/efi/loader/efiserialio.c
> @@ -261,11 +261,11 @@ comc_probe(struct console *sc)
>                 if (comc_port == NULL)
>                         return;
>         }
> -       comc_port->baudrate = COMSPEED;
> +       comc_port->baudrate = 0;
>         comc_port->ioaddr = 0;                  /* default port */
> -       comc_port->databits = 8;                /* 8,n,1 */
> -       comc_port->parity = NoParity;           /* 8,n,1 */
> -       comc_port->stopbits = OneStopBit;       /* 8,n,1 */
> +       comc_port->databits = 0;                /* 8,n,1 */
> +       comc_port->parity = 0;          /* 8,n,1 */
> +       comc_port->stopbits = 0;        /* 8,n,1 */
>         comc_port->ignore_cd = 1;               /* ignore cd */
>         comc_port->rtsdtr_off = 0;              /* rts-dtr is on */
>         comc_port->sio = NULL;
>
> was needed.  Possibly the following would be better:
>
> diff --git a/stand/efi/loader/efiserialio.c b/stand/efi/loader/efiserialio.c
> index 8b3f8e83e0b3..54ee39096685 100644
> --- a/stand/efi/loader/efiserialio.c
> +++ b/stand/efi/loader/efiserialio.c
> @@ -494,8 +494,7 @@ comc_setup(void)
>                 return (false);
>
>         status = comc_port->sio->SetAttributes(comc_port->sio,
> -           comc_port->baudrate, 0, 0, comc_port->parity,
> -           comc_port->databits, comc_port->stopbits);
> +           0, 0, 0, 0, 0, 0);
>         if (EFI_ERROR(status))
>                 return (false);

Following change could avoid freeze in comconsole->c_init().
----------
--- a/stand/efi/loader/efiserialio.c
+++ b/stand/efi/loader/efiserialio.c
@@ -467,8 +467,10 @@ comc_speed_set(struct env_var *ev, int flags,
const void *value)
        if (comc_parse_intval(value, &speed) != CMD_OK)
                return (CMD_ERROR);

-       comc_port->baudrate = speed;
-       (void) comc_setup();
+       if (comc_port->baudrate != speed) {
+               comc_port->baudrate = speed;
+               (void) comc_setup();
+       }

        env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
----------

comc_speed_set sets new speed to comc_port->baudrate and calls comc_setup().
But if the new value of comc_port->baudrate is same as the previous
one, comc_setup() freezes at
    status = comc_port->sio->GetControl(comc_port->sio, &control);

Now, the remaining problem is that the kernel does not start.
Linux and OpenBSD run on the machine, so there should be a solution...

>> 3), I dumped each memory map's VirtualStart and PhysicalStart. All
>> VirtualStart were 0. So overwriting VirutalStart by the value of
>> PhysicalStart and running SetVirtualAddressMap should work. But in
>> reality, it doesn't.
>>   OpenBSD does not use SetVirtualAddress for arm64 and Linux seems to
>> have abandoned it for arm64 in 2019.
>>     https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?id=4e46c2a956215482418d7b315749fb1b6c6bc224
>>   Maybe, we also can avoid SetVirtualAddressMap (by
>> efi_disable_vmap="YES"). In this case, (as you wrote) I should change
>> the kernel to treat VA==PA if VirtualStart is 0. (OpenBSD seems to do
>> so).
>
>
> FreeBSD tends to prefer this... Our kernel needs to cope with cases where it has
> been called (many kexec environments provide PA != VA virtual mappings that we
> can't change).
>
>>
>> About 4), I am completely confused. In elf64_exec in
>> stand/efi/loader/arch/arm64/exec.c, the memory address that the kernel
>> was loaded is calculated as:
>>     entry = efi_translate(ehdr->e_entry);  // which becomes 0xb340000
>> and later kicked as:
>>     (*entry)(modulep);
>> I wrote that this calculation is doubtful, but it was right. I dumped
>> the data at the address 0xb340000 and compared it with the output of
>> objdump -D loader_lua.syms. It turned out that it matched with the
>> kernel's _start code in locore.S.
>> Putting some code that jumps to loader's ImageBase address at the
>> start of kernel's _start did not change anything, so I judged that the
>> kernel is not started at all.
>> The excerpt of the loader's memmap command output is as follows:
>>     Type           Physical           Virtual              #Pages     Attr
>>     LoaderData 0000b33ea000  000000000000  00000000  UC WC WT WB WP RP XP
>>     LoaderCode 0000bb909000  000000000000  000000d1 UC WC WT WB WP RP XP
>> From this output, I wonder if the memory attributes on Yoga C630 is
>> properly implemented, but as XP (exec protect) bit is on, I tried to
>> set it off by DXE services' SetMemoryAttributes() (with a lot of
>> transcription from the standards...).It succeeded, but the kernel
>> still did not run.
>>
>> From this tweet:
>> https://twitter.com/canadianbryan/status/1598053941270679552 and its
>> replies, the Microsoft Arm Developer Kit seems to have similar
>> problem, so if somebody succeeded to run FreeBSD on it, please share
>> the information how to do it.
>
>
> I run other arm64 machines w/o issue with the current code. I've not heard from Allan
> for his changes, nor seen any reviews come through...
>
> Where can one buy one of these systems. It seems just odd-ball enough that I can
> justify picking one up for work...

Currently, a Snapdragon system easy to purchase is the Microsoft Arm
Developer Kit, I suppose. It is about $600.
For laptops, Qualcomm has a list:
https://www.qualcomm.com/products/application/mobile-computing/laptop-device-finder

> Warner