Use the refactored UpdateRegionMapping () to traverse the translation
tables, splitting block entries along the way if required, and apply
a mask + or on each to set or clear the PXN/UXN or RO bits.

For now, the 32-bit ARM versions remain unimplemented.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <[email protected]>
---
 ArmPkg/Include/Library/ArmLib.h            | 24 ++++++
 ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 86 ++++++++++++++++++++
 ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c     | 36 ++++++++
 3 files changed, 146 insertions(+)

diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index c83a5a7f1b3c..b4768841bd9d 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -661,4 +661,28 @@ ArmUnsetCpuActlrBit (
   IN  UINTN    Bits
   );
 
+RETURN_STATUS
+ArmSetMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  );
+
+RETURN_STATUS
+ArmClearMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  );
+
+RETURN_STATUS
+ArmSetMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  );
+
+RETURN_STATUS
+ArmClearMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  );
+
 #endif // __ARM_LIB__
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c 
b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
index e7320e543c7f..8c6d3328adf7 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
@@ -510,6 +510,92 @@ SetMemoryAttributes (
   return RETURN_SUCCESS;
 }
 
+STATIC
+RETURN_STATUS
+ArmSetMemoryRegionAttribute (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length,
+  IN  UINT64                    Attributes,
+  IN  UINT64                    BlockEntryMask
+  )
+{
+  RETURN_STATUS                Status;
+  UINT64                       *RootTable;
+
+  RootTable = ArmGetTTBR0BaseAddress ();
+
+  Status = UpdateRegionMapping (RootTable, BaseAddress, Length, Attributes, 
BlockEntryMask);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  // Invalidate all TLB entries so changes are synced
+  ArmInvalidateTlb ();
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+ArmSetMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  UINT64    Val;
+
+  if (ArmReadCurrentEL () == AARCH64_EL1) {
+    // The PXN bit may only be set for the EL1&0 translation regime.
+    Val = TT_PXN_MASK | TT_UXN_MASK;
+  } else {
+    Val = TT_UXN_MASK;
+  }
+
+  return ArmSetMemoryRegionAttribute (
+           BaseAddress,
+           Length,
+           Val,
+           ~TT_ADDRESS_MASK_BLOCK_ENTRY);
+}
+
+RETURN_STATUS
+ArmClearMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return ArmSetMemoryRegionAttribute (
+           BaseAddress,
+           Length,
+           0,
+           ~(TT_ADDRESS_MASK_BLOCK_ENTRY | TT_PXN_MASK | TT_UXN_MASK));
+}
+
+RETURN_STATUS
+ArmSetMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return ArmSetMemoryRegionAttribute (
+           BaseAddress,
+           Length,
+           TT_AP_RO_RO,
+           ~TT_ADDRESS_MASK_BLOCK_ENTRY);
+}
+
+RETURN_STATUS
+ArmClearMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return ArmSetMemoryRegionAttribute (
+           BaseAddress,
+           Length,
+           TT_AP_NO_RO,
+           ~(TT_ADDRESS_MASK_BLOCK_ENTRY | TT_AP_MASK));
+}
+
 RETURN_STATUS
 EFIAPI
 ArmConfigureMmu (
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c 
b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c
index d035ff3caa40..1287dfb1a9bb 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c
@@ -301,3 +301,39 @@ ArmConfigureMmu (
   ArmEnableMmu();
   return RETURN_SUCCESS;
 }
+
+RETURN_STATUS
+ArmSetMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmClearMemoryRegionNoExec (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmSetMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmClearMemoryRegionReadOnly (
+  IN  EFI_PHYSICAL_ADDRESS      BaseAddress,
+  IN  UINT64                    Length
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
-- 
1.9.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to