Re: UEFI EBS() failures on Lenovo T14s

Ard Biesheuvel
2024-11-28T11:05:22Z

On Thu, 28 Nov 2024 at 11:21, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Thu, 28 Nov 2024 at 11:00, Johan Hovold <johan@kernel.org> wrote:
> >
> > On Thu, Nov 28, 2024 at 09:52:33AM +0100, Ard Biesheuvel wrote:
> >
> ...
> > > In upstream EDK2, the map key is just a monotonic counter that gets
> > > incremented on every memory map update, so one experiment worth
> > > conducting is to repeat the second call to ExitBootServices() a couple
> > > of times, increasing the map key each time.
> >
> > I had already tried repeating the second call (GMM + EBS) by running it
> > in a loop, and I do see the map_key increasing for each iteration (e.g.
> > by 0x1a).
> >
> > > Or use GetMemoryMap() to
> > > just grab the map key without the actual memory map, and printing it
> > > to the console (although the timer is disabled on the first call so
> > > anything that relies on that will be shut down at this point)
> >
> > I just tried adding another inner loop just calling GetMemoryMap() a few
> > times and I see the map_key increasing there too for each iteration
> > (e.g. by 0x6).
> >
> > (The map size remains constant.)
> >
> > I do get the feeling that efi_printk() contributes to the memory map
> > updates, and I can indeed get the reference design fw to similarly fail
> > if I try to print the map_key after each call to GetMemoryMap() in a
> > retry loop.
>
> Per the spec, the only thing you are permitted to call if
> ExitBootServices() fails is GetMemoryMap(), and so this is not a spec
> violation.
>
> If GetMemoryMap() itself causes the map key to assume a different
> value than the one it returns, or if ExitBootServices() invokes event
> callbacks on the second call that may cause the map key to get updated
> before it manages to check it, there is obviously something wrong in
> the firmware implementation.

If you're happy to experiment more, you could try and register a
notification for EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES using
CreateEventEx(), and see if it gets called when ExitBootServices() is
called. That would at least help narrow it down.