qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 6/7] Make the kernel image in the fw_cfg DMA


From: Jordan Justen
Subject: Re: [Qemu-devel] [PATCH v4 6/7] Make the kernel image in the fw_cfg DMA interface bootable
Date: Fri, 02 Oct 2015 17:05:36 -0700
User-agent: alot/0.3.6

On 2015-10-02 06:25:50, Laszlo Ersek wrote:
> On 10/02/15 14:07, Gerd Hoffmann wrote:
> >   Hi,
> > 
> >>> Any -kernel boot on x86 will use either linuxboot.bin or multiboot.bin.
> >>
> >> (Except when your firmware is OVMF -- OVMF has its own LoadLinuxLib. So,
> >> if you decide to extend linuxboot.bin / multiboot.bin with the DMA
> >> capability, that can't regress OVMF by definition, and you certainly
> >> won't hear me complain.)
> > 
> > What does ovmf expect btw?  linux kernel with efi stub I assume?
> 
> That's a hard question for me to answer :) (The library was written /
> ported by Jordan, so I'm not responding from personal memory.)
> 
> In Dec 2014 - Jan 2015, Matt, Paolo, Jordan & myself had a long
> discussion about the different ways to boot an EFI kernel (subject "the
> different ways to boot an EFI kernel"). Ultimately Matt wrote an article:
> 
> http://www.uefidk.com/blog/linux-efi-boot-stub
> 
> To distill the discussion (and I hope Matt will correct me if I'm wrong,
> although I'll be heavily stealing from his emails), there are three ways:
> 
> (1) Legacy EFI boot where the boot loader does *everything*
> (2) EFI boot stub
> (3) EFI handover protocol
> 
> In (1), the boot loader calls ExitBootServices().
> 
> "OvmfPkg/Library/LoadLinuxLib" supports this method, for directly
> booting a kernel from fw_cfg, on the path that it calls "Old kernels
> without EFI handover protocol".
> 
> The problem with (1) is that "all the smarts
> of booting a Linux kernel on EFI platforms are in the boot loader",
> which includes workarounds for platform bugs, and lock-step development
> between kernel and boot loader.
> 
> (2) From Matt: "This method makes the Linux kernel appear to be
> a PE/COFF executable. This allows us to perform bug workarounds early in
> the kernel source because it's the kernel that calls ExitBootServices().
> Additional goodness is obtained by the fact that you no longer need to
> try as hard to keep kernel and boot loader development in sync because
> the boot loader does very little and all smarts are in the kernel."
> 
> The general drawback here is that without a boot loader, you can "only"
> load the kernel image (and the EFI stub of the kernel can "only" load
> the initrd) from filesystems for which the firmware has support (ie.
> those that it exposes with EFI_SIMPLE_FILE_SYSTEM_PROTOCOL interfaces).
> 
> OvmfPkg/Library/LoadLinuxLib does *not* support this method.
> 
> However, ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c does. (In
> fact, for AAVMF, this is the only method supported.) The "drawback"
> remark about filesystems does not apply, because the kernel, initrd and
> cmdline blobs are retrieved from fw_cfg, and exposed in a synthetic
> (memory-only, read-only) EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. Then we launch
> the kernel with gBS->LoadImage() and gBS->StartImage(), and the kernel
> loads the initrd with the standard EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
> member functions.
> 
> (3) From Matt again: 'The third option, the EFI handover protocol, is a
> happy medium between the first two approaches. You split the "EFI boot
> smarts" between the boot loader and EFI boot stub, which allows you to
> a) load files from non-FAT file systems via the boot loader and b) leave
> all the EFI bug workarounds to the kernel developers because the kernel
> is still responsible for calling ExitBootServices().'
> 
> Later Matt also mentioned that under (3) you can have extra bells and
> whistles (graphics etc) in your boot loader, while the kernel still gets
> early firmware access.
> 
> OVMF supports this method too.
> 
> I'll add that the "FAT file system" restriction that (3) is supposed to
> remedy is a bit laxer in general; even without a GRUB-like boot loader,
> you can load a kernel from PXE / TFTP, and generally from anything that
> looks like an EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.
> 
> So the summary is this:
> - OVMF can load "legacy" kernels, implementing an appropriate boot
>   loader and calling ExitBootServices() (1)
> 
> - OVMF can load EFI stubbed kernels, implementing an absolutely minimal
>   boot loader (3)
> 
> - AAVMF can load EFI stubbed kernels only (see the rationale in
>   <https://github.com/tianocore/edk2/commit/23d04b58>), in method (2).
>   This was written by me, and I chose this over (1) and (3) because:
> 
>   - (1) would have never worked / made any sense for aarch64 -- see
>     again the commit msg I referenced,
> 
>   - (3) would have been overkill -- all the extras that could have been
>     granted by an external boot loader were useless here, and the EFI
>     stub dependency of (3) enabled the simpler, direct LoadImage() /
>     StartImage() method.
> 
> ... Paolo asked why OVMF hadn't opted for (2) as well, to which Matt
> replied -- if I understand correctly -- that in parallel with the
> kernel's facilities being developed for (3), OVMF was supposed to
> support / exercise those facilities too.
> 
> Another question was if (2) could be enabled in / ported to OVMF -- it
> could be, yes, but I'm hard pressed for any reason.

I already did this nearly 3 years ago, but then I dropped the ball.

http://thread.gmane.org/gmane.comp.bios.tianocore.devel/925

I'd still like to add this to OVMF, since it enables any old EFI
application to be run with qemu's -kernel parameter. For example, I
was able to launch the EFI shells with it.

-Jordan

> > Could
> > you also load efi apps, i.e. something like "qemu -kernel shell.efi"?
> 
> I seem to remember that this has been suggested by Jordan as well. The
> synthetic file system + LoadImage() + StartImage(), seen in (2), would
> be theoretically suitable for this. However, at least three things
> aren't a good match now:
> 
> - The way the synthetic filesystem is currently populated. One thing we
>   need to put in there is the kernel image, to be launched from the
>   firmware with LoadImage() + StartImage(). However, the kernel uses
>   the filesystem too (it looks for the initrd file there), therefore we
>   populate the fs with that file too. Such a filesystem may not a good
>   match for other EFI executables (especially not if they expect a
>   writeable working directory).
> 
> - If you boot the kernel successfully, then StartImage() never returns.
>   If it returns, then that's mostly considered an error, and the usual
>   boot option processing commences, as if you had never specified
>   "-kernel". This is probably not appropriate when your payload was the
>   UEFI shell: exiting the shell (any shell) is completely normal for a
>   user, and starting to process boot options right after that is
>   probably unexpected / unintended.
> 
> - When the top level kernel boot function returns (due to a genuine
>   kernel boot error, or because "-kernel" wasn't specified,
>   or -- fictively -- because the shell exited normally), the synthetic
>   filesystem is torn down. This is okay for a kernel payload (because if
>   booting it failed for the first time, there's no reason to retry it),
>   but a user might want to reenter (and again exit) the shell any
>   number of times.
> 
> ... I think I prefer to keep the shell built into the firmware, and/or
> to keep it on "UefiShell.iso". I already consider "-kernel" an abuse of
> fw_cfg (one that at this point we can't get rid of any more); let's not
> make it worse. I think the *real* goal here is an easy-to-use,
> zero-config semihosting solution; ie. accessing a host directory tree
> within the guest.
> 
> However, that use case is a burning problem for full-blown guest OS-es
> as well. Assuming we end up with a simple solution, I think I'd prefer
> to implement a UEFI_DRIVER that exposes the same host-side tree as an
> EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instance to the firmware, over
> bastardizing fw_cfg even more.
> 
> I don't yet know how dynamic host-side writes should be shown to guest
> firmware, but in the worst case, I could just return EFI_MEDIA_CHANGED:
> 
>     If the medium is changed while there are open file handles to the
>     volume, all file handles to the volume will return
>     EFI_MEDIA_CHANGED. To access the files on the new medium, the
>     volume must be reopened with OpenVolume().
> 
> Thanks
> Laszlo
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]