From: "Ard Biesheuvel" <ardb@kernel.org>
To: devel@edk2.groups.io, lersek@redhat.com
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>,
Gerd Hoffmann <kraxel@redhat.com>,
Leif Lindholm <quic_llindhol@quicinc.com>,
Oliver Smith-Denny <osde@linux.microsoft.com>,
Oliver Steffen <osteffen@redhat.com>,
Sami Mujawar <sami.mujawar@arm.com>,
Sean Brogan <sean.brogan@microsoft.com>
Subject: Re: [edk2-devel] [PATCH 1/1] ArmVirtPkg/FdtPL011SerialPortLib: initialize implicitly
Date: Fri, 6 Oct 2023 19:08:07 +0200 [thread overview]
Message-ID: <CAMj1kXEPDzP+r=CU91aYWnij9jEvjg9EdVLuuhvpTrt56OeZqQ@mail.gmail.com> (raw)
In-Reply-To: <a28cb7be-6875-9897-eceb-57f19a122778@redhat.com>
On Mon, 2 Oct 2023 at 16:47, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 9/30/23 23:23, Laszlo Ersek wrote:
> > FdtPL011SerialPortLib claims that it's usable from the DXE_CORE. That's
> > not correct: the DXE_CORE calls DEBUG() and ASSERT() before it calls
> > ProcessLibraryConstructorList(). Via the BaseDebugLibSerialPort instance,
> > those DEBUG() and ASSERT() calls result in SerialPortWrite() calls, before
> > ProcessLibraryConstructorList() called either our constructor
> > FdtPL011SerialPortLibInitialize(), or BaseDebugLibSerialPortConstructor().
> >
> > (And even if the DXE_CORE called the latter function early enough, it
> > would just invoke our SerialPortInitialize() function -- which does
> > nothing.)
> >
> > This means that the earliest DXE_CORE debug messages are lost.
> >
> > Rename FdtPL011SerialPortLibInitialize() to SerialPortInitialize(), so
> > that the same initialization occur through the constructor and the public
> > SerialPortInitialize() library API.
> >
> > Turn SerialPortInitialize() calls after the first one into no-ops.
> >
> > Our SerialPortLib APIs already use (mSerialBaseAddress != 0) to track
> > initialization. Rework those checks to actually initialize the library if
> > that hasn't happened yet.
> >
> > The following new lines appear in the log:
> >
> >> CoreInitializeMemoryServices:
> >> BaseAddress - 0x48000000 Length - 0xF8000000 MinimalMemorySizeNeeded - 0x38C8000
> >> InstallProtocolInterface: [EfiLoadedImageProtocol] 46EFC3E0
> >> ProtectUefiImageCommon - 0x46EFC3E0
> >> - 0x0000000046EB2000 - 0x0000000000068000
> >
> > (0x46EB2000 is the load address of the DXE Core.)
> >
> > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> > Cc: Gerd Hoffmann <kraxel@redhat.com>
> > Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> > Cc: Oliver Smith-Denny <osde@linux.microsoft.com>
> > Cc: Oliver Steffen <osteffen@redhat.com>
> > Cc: Sami Mujawar <sami.mujawar@arm.com>
> > Cc: Sean Brogan <sean.brogan@microsoft.com>
> > Reported-by: Oliver Smith-Denny <osde@linux.microsoft.com>
> > Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> > ---
> >
> > Notes:
> > In my opinion this is the wrong approach to fix the bug, but the right
> > approach would require so much work all over edk2 (and outside of it)
> > that it's just not practical.
>
> NB I'd still like this patch to be merged; "wrong approach" is too
> strongly worded. I'd now refine that as "theoretically not 100% pure".
> Merging this one is a compromise, but an easy one -- I had worked
> several hours on the "pure approach", and it absolutely spiralled out of
> control. So this is the only one practical thing to do.
>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
I'll queue this up.
> >
> > ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf | 2 +-
> > ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c | 84 ++++++++++++--------
> > 2 files changed, 52 insertions(+), 34 deletions(-)
> >
> > diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
> > index 2b9a34aa30d1..c417514e3ed5 100644
> > --- a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
> > +++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
> > @@ -15,7 +15,7 @@ [Defines]
> > MODULE_TYPE = BASE
> > VERSION_STRING = 1.0
> > LIBRARY_CLASS = SerialPortLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
> > - CONSTRUCTOR = FdtPL011SerialPortLibInitialize
> > + CONSTRUCTOR = SerialPortInitialize
> >
> > [Sources.common]
> > FdtPL011SerialPortLib.c
> > diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
> > index 614ea5a860b9..9d71f369570f 100644
> > --- a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
> > +++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
> > @@ -23,49 +23,57 @@
> > #include <Library/HobLib.h>
> > #include <Guid/EarlyPL011BaseAddress.h>
> >
> > -STATIC UINTN mSerialBaseAddress;
> > -
> > -RETURN_STATUS
> > -EFIAPI
> > -SerialPortInitialize (
> > - VOID
> > - )
> > -{
> > - return RETURN_SUCCESS;
> > -}
> > +STATIC UINTN mSerialBaseAddress;
> > +STATIC RETURN_STATUS mPermanentStatus = RETURN_SUCCESS;
> >
> > /**
> > -
> > Program hardware of Serial port
> >
> > - @return RETURN_NOT_FOUND if no PL011 base address could be found
> > - Otherwise, result of PL011UartInitializePort () is returned
> > + @retval RETURN_SUCCESS If the serial port was initialized successfully by
> > + this call, or an earlier call, to
> > + SerialPortInitialize().
> >
> > + @retval RETURN_NOT_FOUND If no PL011 base address could be found.
> > +
> > + @return Error codes forwarded from
> > + PL011UartInitializePort().
> > **/
> > RETURN_STATUS
> > EFIAPI
> > -FdtPL011SerialPortLibInitialize (
> > +SerialPortInitialize (
> > VOID
> > )
> > {
> > VOID *Hob;
> > + RETURN_STATUS Status;
> > CONST UINT64 *UartBase;
> > + UINTN SerialBaseAddress;
> > UINT64 BaudRate;
> > UINT32 ReceiveFifoDepth;
> > EFI_PARITY_TYPE Parity;
> > UINT8 DataBits;
> > EFI_STOP_BITS_TYPE StopBits;
> >
> > + if (mSerialBaseAddress != 0) {
> > + return RETURN_SUCCESS;
> > + }
> > +
> > + if (RETURN_ERROR (mPermanentStatus)) {
> > + return mPermanentStatus;
> > + }
> > +
> > Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
> > if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase)) {
> > - return RETURN_NOT_FOUND;
> > + Status = RETURN_NOT_FOUND;
> > + goto Failed;
> > }
> >
> > UartBase = GET_GUID_HOB_DATA (Hob);
> >
> > - mSerialBaseAddress = (UINTN)*UartBase;
> > - if (mSerialBaseAddress == 0) {
> > - return RETURN_NOT_FOUND;
> > + SerialBaseAddress = (UINTN)*UartBase;
> > + if (SerialBaseAddress == 0) {
> > + Status = RETURN_NOT_FOUND;
> > + goto Failed;
> > }
> >
> > BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
> > @@ -74,15 +82,25 @@ FdtPL011SerialPortLibInitialize (
> > DataBits = PcdGet8 (PcdUartDefaultDataBits);
> > StopBits = (EFI_STOP_BITS_TYPE)PcdGet8 (PcdUartDefaultStopBits);
> >
> > - return PL011UartInitializePort (
> > - mSerialBaseAddress,
> > - FixedPcdGet32 (PL011UartClkInHz),
> > - &BaudRate,
> > - &ReceiveFifoDepth,
> > - &Parity,
> > - &DataBits,
> > - &StopBits
> > - );
> > + Status = PL011UartInitializePort (
> > + SerialBaseAddress,
> > + FixedPcdGet32 (PL011UartClkInHz),
> > + &BaudRate,
> > + &ReceiveFifoDepth,
> > + &Parity,
> > + &DataBits,
> > + &StopBits
> > + );
> > + if (RETURN_ERROR (Status)) {
> > + goto Failed;
> > + }
> > +
> > + mSerialBaseAddress = SerialBaseAddress;
> > + return RETURN_SUCCESS;
> > +
> > +Failed:
> > + mPermanentStatus = Status;
> > + return Status;
> > }
> >
> > /**
> > @@ -102,7 +120,7 @@ SerialPortWrite (
> > IN UINTN NumberOfBytes
> > )
> > {
> > - if (mSerialBaseAddress != 0) {
> > + if (!RETURN_ERROR (SerialPortInitialize ())) {
> > return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes);
> > }
> >
> > @@ -126,7 +144,7 @@ SerialPortRead (
> > IN UINTN NumberOfBytes
> > )
> > {
> > - if (mSerialBaseAddress != 0) {
> > + if (!RETURN_ERROR (SerialPortInitialize ())) {
> > return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes);
> > }
> >
> > @@ -146,7 +164,7 @@ SerialPortPoll (
> > VOID
> > )
> > {
> > - if (mSerialBaseAddress != 0) {
> > + if (!RETURN_ERROR (SerialPortInitialize ())) {
> > return PL011UartPoll (mSerialBaseAddress);
> > }
> >
> > @@ -199,7 +217,7 @@ SerialPortSetAttributes (
> > {
> > RETURN_STATUS Status;
> >
> > - if (mSerialBaseAddress == 0) {
> > + if (RETURN_ERROR (SerialPortInitialize ())) {
> > Status = RETURN_UNSUPPORTED;
> > } else {
> > Status = PL011UartInitializePort (
> > @@ -234,7 +252,7 @@ SerialPortSetControl (
> > {
> > RETURN_STATUS Status;
> >
> > - if (mSerialBaseAddress == 0) {
> > + if (RETURN_ERROR (SerialPortInitialize ())) {
> > Status = RETURN_UNSUPPORTED;
> > } else {
> > Status = PL011UartSetControl (mSerialBaseAddress, Control);
> > @@ -261,7 +279,7 @@ SerialPortGetControl (
> > {
> > RETURN_STATUS Status;
> >
> > - if (mSerialBaseAddress == 0) {
> > + if (RETURN_ERROR (SerialPortInitialize ())) {
> > Status = RETURN_UNSUPPORTED;
> > } else {
> > Status = PL011UartGetControl (mSerialBaseAddress, Control);
> >
> >
> >
> >
> >
>
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#109366): https://edk2.groups.io/g/devel/message/109366
Mute This Topic: https://groups.io/mt/101682671/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2023-10-06 17:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-30 21:23 [edk2-devel] [PATCH 1/1] ArmVirtPkg/FdtPL011SerialPortLib: initialize implicitly Laszlo Ersek
2023-10-02 14:47 ` Laszlo Ersek
2023-10-06 17:08 ` Ard Biesheuvel [this message]
2023-10-08 9:16 ` Laszlo Ersek
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='CAMj1kXEPDzP+r=CU91aYWnij9jEvjg9EdVLuuhvpTrt56OeZqQ@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