When the payload runs under an outer UEFI (via ChainloadApp) the
PL031 register range is already present in the GCD map because
UefiPayloadEntry publishes every MMIO region reported by the
bootloader as EfiGcdMemoryTypeMemoryMappedIo.  AddMemorySpace()
then returns EFI_ACCESS_DENIED and LibRtcInitialize() bails out,
so the runtime clock is never installed.

Tolerate that case: query the existing descriptor and proceed
only if it is already MemoryMappedIo.  Since the pre-existing
descriptor typically does not advertise EFI_MEMORY_RUNTIME in
its Capabilities, extend the capability set before
SetMemorySpaceAttributes() so the RUNTIME attribute can be
applied.

The check keeps the original error handling for genuine
conflicts (system RAM, or a range owned by another driver).

A platform where this driver legitimately owns the range still takes
the AddMemorySpace() success path, and previously EFI_ACCESS_DENIED
meant the RTC was simply not installed -- so no platform that works
today can regress.  ChainloadApp, added later in this series, is the
motivating case.

Cc: Ard Biesheuvel <[email protected]>
Cc: Leif Lindholm <[email protected]>
Cc: Sami Mujawar <[email protected]>
Assisted-by: claude-opus-5
Signed-off-by: Alexander Graf <[email protected]>
---
 .../PL031RealTimeClockLib.c                   | 66 ++++++++++++++++++-
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git 
a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c 
b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
index fb353cf2df..2b4b9d0754 100644
--- a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
+++ b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
@@ -321,7 +321,8 @@ LibRtcInitialize (
   IN EFI_SYSTEM_TABLE  *SystemTable

   )

 {

-  EFI_STATUS  Status;

+  EFI_STATUS                       Status;

+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Desc;

 

   // Initialize RTC Base Address

   mPL031RtcBase = PcdGet32 (PcdPL031RtcBase);

@@ -333,7 +334,68 @@ LibRtcInitialize (
                   SIZE_4KB,

                   EFI_MEMORY_UC | EFI_MEMORY_RUNTIME | EFI_MEMORY_XP

                   );

-  if (EFI_ERROR (Status)) {

+  if (Status == EFI_ACCESS_DENIED) {

+    //

+    // The range is already present in the GCD map, e.g. because a

+    // preceding platform driver or the payload's own MMIO discovery

+    // added it.  That is only acceptable if the existing descriptor

+    // is MMIO; refuse to touch anything else.

+    //

+    Status = gDS->GetMemorySpaceDescriptor (mPL031RtcBase, &Desc);

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    //

+    // AddMemorySpace() reports EFI_ACCESS_DENIED if any part of the

+    // requested range is already present, while GetMemorySpaceDescriptor()

+    // only returns the descriptor that contains the base address.  The

+    // descriptor therefore says nothing about the rest of the range: a

+    // request that straddles this descriptor and another one would be

+    // accepted on the strength of the first descriptor alone.  Require the

+    // whole range to lie inside it.

+    //

+    if ((Desc.BaseAddress > mPL031RtcBase) ||

+        ((Desc.BaseAddress + Desc.Length) <

+         ((UINT64)mPL031RtcBase + SIZE_4KB)))

+    {

+      return EFI_ACCESS_DENIED;

+    }

+

+    if ((Desc.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) ||

+        (Desc.ImageHandle != NULL))

+    {

+      return EFI_ACCESS_DENIED;

+    }

+

+    //

+    // A pre-existing MMIO descriptor need not carry every capability that

+    // the SetMemorySpaceAttributes() call below requests, and

+    // CoreSetMemorySpaceAttributes() rejects any attribute that is absent

+    // from Capabilities with EFI_UNSUPPORTED.  Add the full set that is

+    // about to be requested, not just EFI_MEMORY_RUNTIME.

+    //

+    if ((Desc.Capabilities &

+         (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME | EFI_MEMORY_XP)) !=

+        (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME | EFI_MEMORY_XP))

+    {

+      Status = gDS->SetMemorySpaceCapabilities (

+                      mPL031RtcBase,

+                      SIZE_4KB,

+                      Desc.Capabilities | EFI_MEMORY_UC |

+                      EFI_MEMORY_RUNTIME | EFI_MEMORY_XP

+                      );

+      if (EFI_ERROR (Status)) {

+        DEBUG ((

+          DEBUG_WARN,

+          "%a: SetMemorySpaceCapabilities() failed: %r\n",

+          __func__,

+          Status

+          ));

+        return Status;

+      }

+    }

+  } else if (EFI_ERROR (Status)) {

     return Status;

   }

 

-- 
2.47.3



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#122083): https://edk2.groups.io/g/devel/message/122083
Mute This Topic: https://groups.io/mt/120797179/21656
Group Owner: [email protected]
Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to