From: "Ard Biesheuvel" <ard.biesheuvel@linaro.org>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>,
Leif Lindholm <leif.lindholm@linaro.org>,
"Ni, Ray" <ray.ni@intel.com>, Andrew Fish <afish@apple.com>
Subject: Re: [RFC PATCH] ArmPkg/PlatformBmLib: defer GOP console discovery after Driver#### dispatch
Date: Wed, 15 Jan 2020 14:02:52 +0100 [thread overview]
Message-ID: <CAKv+Gu-9mge0UXh6-OdJ_iw1Yf1F57ayDy_6q03SRU9nzzVzWA@mail.gmail.com> (raw)
In-Reply-To: <23a9be06-791f-517a-ccd4-fd36c93af8b0@redhat.com>
On Wed, 15 Jan 2020 at 13:50, Laszlo Ersek <lersek@redhat.com> wrote:
>
> Hi Ard,
>
Hi Laszlo,
Thanks for taking a look.
> On 01/15/20 11:22, Ard Biesheuvel wrote:
> > Currently, ArmPkg's implementation of PlatformBootManagerBeforeConsole()
> > iterates over all PCI I/O handles in the database and connects the ones
> > that may produce an instance of the Graphics Output Protocol (GOP) once
> > connected. After that, it enumerates all the GOP instances and adds them
> > to the stdout/stderr console variables so that they will be used for
> > console output.
> >
> > At this point in the boot, the BDS has not dispatched drivers loaded via
> > Driver#### options yet, making Driver#### options unsuitable for loading
> > drivers that are needed to produce GOP consoles. This is unfortunate, since
> > it prevents us from using commodity GFX hardware that ships without AARCH64
> > option ROMs on AARCH64 hardware and load the driver from the ESP.
> >
> > So let's fix this, by deferring the discovery of PCI backed GOP instances
> > until PlatformBootManagerAfterConsole(). Note that non-PCI GOP instances
> > are still connected in the original spot, so platform framebuffers will
> > still work as before. Also note that the entire dance of connecting PCI
> > root bridges and I/O handles, matching PCI class codes and updating console
> > variables is all encapsulated in EfiBootManagerConnectVideoController(),
> > so let's just call that from PlatformBootManagerAfterConsole().
>
> I too have learned about the EfiBootManagerConnectVideoController() ACPI
> just recently, when Ray mentioned it.
>
> (1) When we call EfiBootManagerConnectVideoController() with a NULL
> parameter, it further calls BmGetVideoController(), which does the
> "dance" you mention. This wasn't obvious to me from the commit message,
> so I'd suggest mentioning BmGetVideoController() there, by name.
>
OK
> >
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > ---
> >
> > Tested on AMD Overdrive with an AMD Radeon GPU plugged in and the
> > AARCH64 AmdGop.efi driver loaded via Driver0000.
> >
> > ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c | 81 ++------------------
> > 1 file changed, 7 insertions(+), 74 deletions(-)
> >
> > diff --git a/ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c
> > index e6e788e0f107..7c63a7b98847 100644
> > --- a/ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c
> > +++ b/ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c
> > @@ -219,66 +219,6 @@ FilterAndProcess (
> > }
> >
> >
> > -/**
> > - This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
> > -**/
> > -STATIC
> > -BOOLEAN
> > -EFIAPI
> > -IsPciDisplay (
> > - IN EFI_HANDLE Handle,
> > - IN CONST CHAR16 *ReportText
> > - )
> > -{
> > - EFI_STATUS Status;
> > - EFI_PCI_IO_PROTOCOL *PciIo;
> > - PCI_TYPE00 Pci;
> > -
> > - Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,
> > - (VOID**)&PciIo);
> > - if (EFI_ERROR (Status)) {
> > - //
> > - // This is not an error worth reporting.
> > - //
> > - return FALSE;
> > - }
> > -
> > - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,
> > - sizeof Pci / sizeof (UINT32), &Pci);
> > - if (EFI_ERROR (Status)) {
> > - DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
> > - return FALSE;
> > - }
> > -
> > - return IS_PCI_DISPLAY (&Pci);
> > -}
> > -
> > -
> > -/**
> > - This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
> > - the matching driver to produce all first-level child handles.
> > -**/
> > -STATIC
> > -VOID
> > -EFIAPI
> > -Connect (
> > - IN EFI_HANDLE Handle,
> > - IN CONST CHAR16 *ReportText
> > - )
> > -{
> > - EFI_STATUS Status;
> > -
> > - Status = gBS->ConnectController (
> > - Handle, // ControllerHandle
> > - NULL, // DriverImageHandle
> > - NULL, // RemainingDevicePath -- produce all children
> > - FALSE // Recursive
> > - );
> > - DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",
> > - __FUNCTION__, ReportText, Status));
> > -}
> > -
> > -
> > /**
> > This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
> > handle, and adds it to ConOut and ErrOut.
> > @@ -554,20 +494,6 @@ PlatformBootManagerBeforeConsole (
> > //
> > EfiBootManagerDispatchDeferredImages ();
> >
> > - //
> > - // Locate the PCI root bridges and make the PCI bus driver connect each,
> > - // non-recursively. This will produce a number of child handles with PciIo on
> > - // them.
> > - //
> > - FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
> > -
> > - //
> > - // Find all display class PCI devices (using the handles from the previous
> > - // step), and connect them non-recursively. This should produce a number of
> > - // child handles with GOPs on them.
> > - //
> > - FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
> > -
> > //
> > // Now add the device path of all handles with GOP on them to ConOut and
> > // ErrOut.
>
> (2) Second, BmGetVideoController() differs from the logic that's being
> removed here. I see two differences:
>
> (2a) the IsPciDisplay() helper function uses IS_PCI_DISPLAY(), while
> BmGetVideoController() uses IS_PCI_VGA().
>
> Interestingly, there is a comment:
>
> // TODO: use IS_PCI_DISPLAY??
>
> If I understand correctly, IS_PCI_VGA() matches a subset of
> IS_PCI_DISPLAY(), namely the such devices that offer legacy BIOS VGA
> interfaces (IO ports and whatnot). In support of my understanding,
> please see:
>
> - 4fdb585c69d6 ("OvmfPkg/PlatformBootManagerLib: relax device class
> requirement for ConOut", 2016-09-01)
>
> - commit 70dbd16361ee ("OvmfPkg/QemuVideoDxe: Add SubClass field to
> QEMU_VIDEO_CARD", 2018-05-17)
>
> Thus, IS_PCI_VGA() appears overly restrictive *especially* on AARCH64,
> where you are more likely to encounter "VGA legacy"-free PCI graphics
> cards than on x86.
>
> Now, this doesn't necessarily mean "ArmPkg/PlatformBmLib" needs to use
> its own IS_PCI_DISPLAY logic -- we could also turn the comment in
> BmGetVideoController() into actual code, as an alternative.
>
I think that would be a worthwhile separate change, although for bare
metal platforms today, it doesn't really make a difference, given
that, AFAICT, non-VGA PCI display controllers are rare, if they exist
at all.
> (2b) The other difference is that BmGetVideoController() only grabs the
> first video controller it finds, and runs with it. Whereas, logic being
> removed here would connect (and add, to ConOut/StdErr) *all* PCI video
> controllers. I think that's nicer in a multi-controller setup.
>
True.
> > @@ -674,6 +600,13 @@ PlatformBootManagerAfterConsole (
> > UINTN PosX;
> > UINTN PosY;
> >
> > + //
> > + // Defer this call to PlatformBootManagerAfterConsole () so that devices
> > + // managed by drivers that were loaded via Driver#### options are covered
> > + // as well.
> > + //
> > + EfiBootManagerConnectVideoController (NULL);
> > +
> > FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
> >
> > //
> >
>
> (3) So how about the following approach:
>
> (3a) factor the following sequence:
>
> FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
> FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
>
> out to a helper function,
>
> (3b) call the extracted sequence in *both* its current place, *and* at
> the top of PlatformBootManagerAfterConsole() (instead of
> EfiBootManagerConnectVideoController())?
>
> ?
>
> I expect this should give you *some* consoles in BeforeConsole() (on
> such PCI and non-PCI graphics controllers whose drivers are in the
> platform firmware), just to be safe; and *all* the rest would be picked
> up in AfterConsole().
>
I wonder whether there is a point to doing it twice, regardless of
whether we are talking about PCI or non-PCI. I experimented with just
moving those calls to AfterConsole(), and I get basically the same
behavior as with this patch.
next prev parent reply other threads:[~2020-01-15 13:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-15 10:22 [RFC PATCH] ArmPkg/PlatformBmLib: defer GOP console discovery after Driver#### dispatch Ard Biesheuvel
2020-01-15 12:50 ` Laszlo Ersek
2020-01-15 13:02 ` Ard Biesheuvel [this message]
2020-01-15 14:52 ` Laszlo Ersek
2020-01-15 14:58 ` Ard Biesheuvel
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-list 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=CAKv+Gu-9mge0UXh6-OdJ_iw1Yf1F57ayDy_6q03SRU9nzzVzWA@mail.gmail.com \
--to=devel@edk2.groups.io \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox