public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: edk2-devel@lists.01.org, leif.lindholm@linaro.org
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: [PATCH v2] ArmPlatformPkg/NorFlashDxe: use strictly aligned CopyMem()
Date: Fri,  9 Sep 2016 13:18:22 +0100	[thread overview]
Message-ID: <1473423502-7061-1-git-send-email-ard.biesheuvel@linaro.org> (raw)

The UEFI spec stipulates that unaligned accesses should be enabled
on CPUs that support them, which means all of them, given that we
no longer support pre-v7 ARM cores, and the AARCH64 bindings mandate
support for unaligned accesses unconditionally.

This means that one should not assume that CopyMem () is safe to call
on regions that may be mapped using device attributes, which is the
case for the NOR flash. Since we have no control over the mappings when
running under the OS, and given that write accesses require device
mappings, we should not call CopyMem () in the read path either, but
use our own implementation that is guaranteed to take alignment into
account.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
v2:
- simplify the AlignedCopyMem () implementation, given that we do not require
  memmove() semantics for copying between NOR flash and memory
- document the above
- add macro to perform alignment check
- drop redundant/unnecessary casts and parentheses

 ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 63 +++++++++++++++++++-
 1 file changed, 61 insertions(+), 2 deletions(-)

diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
index 3abbe5cb32bc..ca61ac5e1983 100644
--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
+++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -744,6 +744,65 @@ NorFlashWriteBlocks (
   return Status;
 }
 
+#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
+
+/**
+  Copy Length bytes from Source to Destination, using aligned accesses only.
+  Note that this implementation uses memcpy() semantics rather then memmove()
+  semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
+
+  @param  DestinationBuffer The target of the copy request.
+  @param  SourceBuffer      The place to copy from.
+  @param  Length            The number of bytes to copy.
+
+  @return Destination
+
+**/
+STATIC
+VOID *
+AlignedCopyMem (
+  OUT     VOID                      *DestinationBuffer,
+  IN      CONST VOID                *SourceBuffer,
+  IN      UINTN                     Length
+  )
+{
+  UINT8             *Destination8;
+  CONST UINT8       *Source8;
+  UINT32            *Destination32;
+  CONST UINT32      *Source32;
+  UINT64            *Destination64;
+  CONST UINT64      *Source64;
+
+  if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 8) && Length >= 8) {
+    Destination64 = DestinationBuffer;
+    Source64 = SourceBuffer;
+    while (Length >= 8) {
+      *Destination64++ = *Source64++;
+      Length -= 8;
+    }
+
+    Destination8 = (UINT8 *)Destination64;
+    Source8 = (CONST UINT8 *)Source64;
+  } else if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 4) && Length >= 4) {
+    Destination32 = DestinationBuffer;
+    Source32 = SourceBuffer;
+    while (Length >= 4) {
+      *Destination32++ = *Source32++;
+      Length -= 4;
+    }
+
+    Destination8 = (UINT8 *)Destination32;
+    Source8 = (CONST UINT8 *)Source32;
+  } else {
+    Destination8 = DestinationBuffer;
+    Source8 = SourceBuffer;
+  }
+  while (Length-- != 0) {
+    *Destination8++ = *Source8++;
+  }
+  return DestinationBuffer;
+}
+
 EFI_STATUS
 NorFlashReadBlocks (
   IN NOR_FLASH_INSTANCE   *Instance,
@@ -791,7 +850,7 @@ NorFlashReadBlocks (
   SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
 
   // Readout the data
-  CopyMem(Buffer, (UINTN *)StartAddress, BufferSizeInBytes);
+  AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
 
   return EFI_SUCCESS;
 }
@@ -832,7 +891,7 @@ NorFlashRead (
   SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
 
   // Readout the data
-  CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes);
+  AlignedCopyMem (Buffer, (VOID *)StartAddress + Offset, BufferSizeInBytes);
 
   return EFI_SUCCESS;
 }
-- 
2.7.4



             reply	other threads:[~2016-09-09 12:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-09 12:18 Ard Biesheuvel [this message]
2016-09-09 12:34 ` [PATCH v2] ArmPlatformPkg/NorFlashDxe: use strictly aligned CopyMem() Leif Lindholm
2016-09-09 12:59   ` 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=1473423502-7061-1-git-send-email-ard.biesheuvel@linaro.org \
    --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